package com.mindskip.xzs.controller.student;

import com.github.pagehelper.PageInfo;
import com.mindskip.xzs.base.BaseApiController;
import com.mindskip.xzs.base.RestResponse;
import com.mindskip.xzs.domain.*;
import com.mindskip.xzs.domain.enums.ExamPaperAnswerStatusEnum;
import com.mindskip.xzs.event.CalculateExamPaperAnswerCompleteEvent;
import com.mindskip.xzs.event.UserEvent;
import com.mindskip.xzs.service.ExamPaperAnswerService;
import com.mindskip.xzs.service.ExamPaperService;
import com.mindskip.xzs.service.SubjectService;
import com.mindskip.xzs.utility.DateTimeUtil;
import com.mindskip.xzs.utility.ExamUtil;
import com.mindskip.xzs.utility.PageInfoHelper;
import com.mindskip.xzs.viewmodel.admin.exam.ExamPaperEditRequestVM;
import com.mindskip.xzs.viewmodel.admin.question.QuestionEditRequestVM;
import com.mindskip.xzs.viewmodel.student.exam.ExamPaperReadVM;
import com.mindskip.xzs.viewmodel.student.exam.ExamPaperSubmitItemVM;
import com.mindskip.xzs.viewmodel.student.exam.ExamPaperSubmitVM;
import com.mindskip.xzs.viewmodel.student.exampaper.ExamPaperAnswerPageResponseVM;
import com.mindskip.xzs.viewmodel.student.exampaper.ExamPaperAnswerPageVM;

import lombok.extern.slf4j.Slf4j;

import com.mindskip.xzs.viewmodel.student.exampaper.AiScoreQuestionRequestVM;
import com.mindskip.xzs.viewmodel.student.exampaper.AiScoreQuestionResponseVM;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.validation.Valid;
import java.util.*;

@RestController("StudentExamPaperAnswerController")
@RequestMapping(value = "/api/student/exampaper/answer")
@Slf4j
public class ExamPaperAnswerController extends BaseApiController {

    private final ExamPaperAnswerService examPaperAnswerService;
    private final ExamPaperService examPaperService;
    private final SubjectService subjectService;
    private final ApplicationEventPublisher eventPublisher;

    @Autowired
    public ExamPaperAnswerController(ExamPaperAnswerService examPaperAnswerService,
            ExamPaperService examPaperService,
            SubjectService subjectService,
            ApplicationEventPublisher eventPublisher) {
        this.examPaperAnswerService = examPaperAnswerService;
        this.examPaperService = examPaperService;
        this.subjectService = subjectService;
        this.eventPublisher = eventPublisher;
    }

    @RequestMapping(value = "/pageList", method = RequestMethod.POST)
    public RestResponse<PageInfo<ExamPaperAnswerPageResponseVM>> pageList(
            @RequestBody @Valid ExamPaperAnswerPageVM model) {
        model.setCreateUser(getCurrentUser().getId());
        PageInfo<ExamPaperAnswer> pageInfo = examPaperAnswerService.studentPage(model);
        PageInfo<ExamPaperAnswerPageResponseVM> page = PageInfoHelper.copyMap(pageInfo, e -> {
            ExamPaperAnswerPageResponseVM vm = modelMapper.map(e, ExamPaperAnswerPageResponseVM.class);
            Subject subject = subjectService.selectById(vm.getSubjectId());
            vm.setDoTime(ExamUtil.secondToVM(e.getDoTime()));
            vm.setSystemScore(ExamUtil.scoreToVM(e.getSystemScore()));
            vm.setUserScore(ExamUtil.scoreToVM(e.getUserScore()));
            vm.setPaperScore(ExamUtil.scoreToVM(e.getPaperScore()));
            vm.setSubjectName(subject.getName());
            vm.setCreateTime(DateTimeUtil.dateFormat(e.getCreateTime()));
            return vm;
        });
        return RestResponse.ok(page);
    }

    @RequestMapping(value = "/answerSubmit", method = RequestMethod.POST)
    public RestResponse answerSubmit(@RequestBody @Valid ExamPaperSubmitVM examPaperSubmitVM) {
        User user = getCurrentUser();
        ExamPaperAnswerInfo examPaperAnswerInfo = examPaperAnswerService.calculateExamPaperAnswer(examPaperSubmitVM,
                user);
        if (null == examPaperAnswerInfo) {
            return RestResponse.fail(2, "试卷不能重复做");
        }
        ExamPaperAnswer examPaperAnswer = examPaperAnswerInfo.getExamPaperAnswer();
        Integer userScore = examPaperAnswer.getUserScore();
        String scoreVm = ExamUtil.scoreToVM(userScore);
        UserEventLog userEventLog = new UserEventLog(user.getId(), user.getUserName(), user.getRealName(), new Date());
        String content = user.getUserName() + " 提交试卷：" + examPaperAnswerInfo.getExamPaper().getName()
                + " 得分：" + scoreVm
                + " 耗时：" + ExamUtil.secondToVM(examPaperAnswer.getDoTime());
        userEventLog.setContent(content);
        eventPublisher.publishEvent(new CalculateExamPaperAnswerCompleteEvent(examPaperAnswerInfo));
        eventPublisher.publishEvent(new UserEvent(userEventLog));
        return RestResponse.ok(scoreVm);
    }

    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    public RestResponse edit(@RequestBody @Valid ExamPaperSubmitVM examPaperSubmitVM) {
        boolean notJudge = examPaperSubmitVM.getAnswerItems().stream()
                .anyMatch(i -> i.getDoRight() == null && i.getScore() == null);
        if (notJudge) {
            return RestResponse.fail(2, "有未批改题目");
        }

        ExamPaperAnswer examPaperAnswer = examPaperAnswerService.selectById(examPaperSubmitVM.getId());
        ExamPaperAnswerStatusEnum examPaperAnswerStatusEnum = ExamPaperAnswerStatusEnum
                .fromCode(examPaperAnswer.getStatus());
        if (examPaperAnswerStatusEnum == ExamPaperAnswerStatusEnum.Complete) {
            return RestResponse.fail(3, "试卷已完成");
        }
        String score = examPaperAnswerService.judge(examPaperSubmitVM);
        User user = getCurrentUser();
        UserEventLog userEventLog = new UserEventLog(user.getId(), user.getUserName(), user.getRealName(), new Date());
        String content = user.getUserName() + " 批改试卷：" + examPaperAnswer.getPaperName() + " 得分：" + score;
        userEventLog.setContent(content);
        eventPublisher.publishEvent(new UserEvent(userEventLog));
        return RestResponse.ok(score);
    }

    @RequestMapping(value = "/read/{id}", method = RequestMethod.POST)
    public RestResponse<ExamPaperReadVM> read(@PathVariable Integer id) {
        ExamPaperAnswer examPaperAnswer = examPaperAnswerService.selectById(id);
        ExamPaperReadVM vm = new ExamPaperReadVM();
        ExamPaperEditRequestVM paper = examPaperService.examPaperToVM(examPaperAnswer.getExamPaperId());
        ExamPaperSubmitVM answer = examPaperAnswerService.examPaperAnswerToVM(examPaperAnswer.getId());
        vm.setPaper(paper);
        vm.setAnswer(answer);
        return RestResponse.ok(vm);
    }

    /**
     * AI分析试卷答题情况
     * 
     * @param id 试卷答案ID
     * @return AI分析结果
     */
    @RequestMapping(value = "/aiAnalyze/{id}", method = RequestMethod.POST)
    public RestResponse aiAnalyzePaper(@PathVariable Integer id) {
        User user = getCurrentUser();
        ExamPaperAnswer examPaperAnswer = examPaperAnswerService.selectById(id);

        // 验证权限
        if (examPaperAnswer == null || !examPaperAnswer.getCreateUser().equals(user.getId())) {
            return RestResponse.fail(2, "试卷不存在或无权限");
        }

        // 获取试卷详情
        ExamPaper examPaper = examPaperService.selectById(examPaperAnswer.getExamPaperId());
        if (examPaper == null) {
            return RestResponse.fail(2, "试卷信息不存在");
        }

        // 获取试卷答题详情
        ExamPaperEditRequestVM paper = examPaperService.examPaperToVM(examPaperAnswer.getExamPaperId());
        ExamPaperSubmitVM answer = examPaperAnswerService.examPaperAnswerToVM(examPaperAnswer.getId());

        try {
            // 构建请求AI分析的数据
            Map<String, Object> requestBody = new HashMap<>();
            // 构建提示信息
            StringBuilder promptBuilder = new StringBuilder();
            promptBuilder.append("请分析以下试卷答题情况，并给出详细的分析报告，包括整体表现、优势题型、待提高题型、学习建议和推荐资料。\n\n");
            promptBuilder.append("格式要求：\n");
            promptBuilder.append("1. 每个部分使用对应的标题（整体表现、优势题型、待提高题型、学习建议、推荐资料）\n");
            promptBuilder.append("2. 每个要点使用破折号（-）开头，不要使用数字编号\n");
            promptBuilder.append("3. 不要使用Markdown格式的分隔符或标题标记\n");
            promptBuilder.append("4. 内容简洁清晰，避免重复\n\n");
            promptBuilder.append("试卷名称：").append(examPaper.getName()).append("\n");
            promptBuilder.append("总分：").append(examPaper.getScore()).append("\n");
            promptBuilder.append("得分：").append(examPaperAnswer.getUserScore()).append("\n");
            promptBuilder.append("答题时间：").append(ExamUtil.secondToVM(examPaperAnswer.getDoTime())).append("\n\n");

            // 添加题目答题情况 - 直接使用 paper 和 answer 构建
            promptBuilder.append("题目答题情况：\n");

            // 遍历试卷中的题目和答案
            for (int i = 0; i < paper.getTitleItems().size(); i++) {
                for (int j = 0; j < paper.getTitleItems().get(i).getQuestionItems().size(); j++) {
                    // 获取题目信息
                    QuestionEditRequestVM questionItem = paper.getTitleItems().get(i).getQuestionItems()
                            .get(j);
                    int itemOrder = questionItem.getItemOrder();

                    // 获取对应的答案信息
                    ExamPaperSubmitItemVM answerItem = null;
                    for (ExamPaperSubmitItemVM item : answer.getAnswerItems()) {
                        if (item.getItemOrder() == itemOrder) {
                            answerItem = item;
                            break;
                        }
                    }

                    if (answerItem != null) {
                        String correctStatus = answerItem.getDoRight() ? "正确" : "错误";
                        promptBuilder.append("题目").append(itemOrder).append("：\n");
                        // 添加题目类型
                        promptBuilder.append("  题型：").append(getQuestionTypeName(questionItem.getQuestionType()))
                                .append("\n");
                        // 添加题目内容
                        promptBuilder.append("  题干：").append(questionItem.getTitle()).append("\n");
                        // 添加正确答案
                        promptBuilder.append("  正确答案：").append(questionItem.getCorrect()).append("\n");
                        // 添加学生答案
                        promptBuilder.append("  学生答案：").append(answerItem.getContent()).append("\n");
                        // 添加得分情况
                        promptBuilder.append("  得分：").append(answerItem.getScore())
                                .append("/").append(questionItem.getScore()).append("\n");
                        // 添加正确状态
                        promptBuilder.append("  状态：").append(correctStatus).append("\n");
                        // 如果有题目分析，也添加进去
                        if (questionItem.getAnalyze() != null && !questionItem.getAnalyze().isEmpty()) {
                            promptBuilder.append("  题目分析：").append(questionItem.getAnalyze()).append("\n");
                        }
                        promptBuilder.append("\n"); // 添加空行分隔不同题目
                    }
                }
            }

            // 请求AI分析
            Map<String, Object> message = new HashMap<>();
            message.put("role", "user");
            message.put("content", promptBuilder.toString());

            List<Map<String, Object>> messages = new ArrayList<>();
            messages.add(message);

            requestBody.put("model", "qwen-plus");
            requestBody.put("messages", messages);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + "sk-78bc57a7c914408abcd14ef11ca92a79");

            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
            RestTemplate restTemplate = new RestTemplate();

            // 发送请求
            ResponseEntity<Map> response = restTemplate.exchange(
                    "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
                    HttpMethod.POST,
                    entity,
                    Map.class);

            // 解析响应
            Map<String, Object> responseBody = response.getBody();
            if (responseBody != null && responseBody.containsKey("choices")) {
                List<Map<String, Object>> choices = (List<Map<String, Object>>) responseBody.get("choices");
                if (choices.size() > 0) {
                    Map<String, Object> choice = choices.get(0);
                    Map<String, Object> messageResponse = (Map<String, Object>) choice.get("message");
                    String content = (String) messageResponse.get("content");

                    // 解析AI回复内容，提取分析结果
                    Map<String, String> analysisResult = parseAIResponse(content);
                    return RestResponse.ok(analysisResult);
                }
            }

            return RestResponse.fail(2, "AI分析失败");
        } catch (Exception e) {
            e.printStackTrace();
            return RestResponse.fail(2, "AI分析请求异常: " + e.getMessage());
        }
    }

    /**
     * 解析AI回复内容，提取分析结果
     * 
     * @param content AI回复内容
     * @return 分析结果
     */
    private Map<String, String> parseAIResponse(String content) {
        Map<String, String> result = new HashMap<>();

        // 提取整体表现
        result.put("overview", extractSection(content, "整体表现", "优势题型"));

        // 提取优势题型
        result.put("strengths", extractSection(content, "优势题型", "待提高题型"));

        // 提取待提高题型
        result.put("weaknesses", extractSection(content, "待提高题型", "学习建议"));

        // 提取学习建议
        result.put("recommendations", extractSection(content, "学习建议", "推荐资料"));

        // 提取推荐资料
        result.put("resources", extractSection(content, "推荐资料", null));

        return result;
    }

    /**
     * 从文本中提取指定部分的内容
     * 
     * @param content     完整文本
     * @param startMarker 开始标记
     * @param endMarker   结束标记
     * @return 提取的内容
     */
    private String extractSection(String content, String startMarker, String endMarker) {
        int startIndex = content.indexOf(startMarker);
        if (startIndex == -1) {
            return "";
        }

        startIndex = content.indexOf(":", startIndex) + 1;
        if (startIndex == 0) {
            startIndex = content.indexOf("：", content.indexOf(startMarker)) + 1;
        }

        if (startIndex == 0) {
            return "";
        }

        int endIndex;
        if (endMarker != null) {
            endIndex = content.indexOf(endMarker, startIndex);
            if (endIndex == -1) {
                endIndex = content.length();
            }
        } else {
            endIndex = content.length();
        }

        return content.substring(startIndex, endIndex).trim();
    }

    /**
     * 获取题目类型名称
     * 
     * @param questionType 题目类型编码
     * @return 题目类型名称
     */
    private String getQuestionTypeName(Integer questionType) {
        switch (questionType) {
            case 1:
                return "单选题";
            case 2:
                return "多选题";
            case 3:
                return "判断题";
            case 4:
                return "填空题";
            case 5:
                return "简答题";
            default:
                return "未知题型";
        }
    }

    /**
     * AI评分接口
     * 
     * @param model 评分请求参数
     * @return 评分结果
     */
    @RequestMapping(value = "/aiScoreQuestion", method = RequestMethod.POST)
    public RestResponse<AiScoreQuestionResponseVM> aiScoreQuestion(@RequestBody @Valid AiScoreQuestionRequestVM model) {
        try {
            // 构建AI请求
            Map<String, Object> requestBody = new HashMap<>();
            List<Map<String, Object>> messageList = new ArrayList<>();

            // 构建系统消息
            Map<String, Object> systemMessage = new HashMap<>();
            systemMessage.put("role", "system");
            systemMessage.put("content", "你是一位专业的教育评分助手，负责根据标准答案评价学生的回答并给出合理的分数。");
            messageList.add(systemMessage);

            // 构建用户消息（提示词）
            Map<String, Object> userMessage = new HashMap<>();
            userMessage.put("role", "user");

            // 构建评分提示词
            String prompt = buildScoringPrompt(model);
            userMessage.put("content", prompt);
            messageList.add(userMessage);

            // 设置AI模型和消息
            requestBody.put("model", "qwen-plus");
            requestBody.put("messages", messageList);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + "sk-78bc57a7c914408abcd14ef11ca92a79");

            // 创建HTTP请求实体
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
            RestTemplate restTemplate = new RestTemplate();

            // 发送请求到AI服务
            ResponseEntity<Map> response = restTemplate.exchange(
                    "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
                    HttpMethod.POST,
                    entity,
                    Map.class);

            // 解析AI返回的结果
            Map<String, Object> responseBody = response.getBody();
            Map<String, Object> choices = ((List<Map<String, Object>>) responseBody.get("choices")).get(0);
            Map<String, Object> message = (Map<String, Object>) choices.get("message");
            String content = (String) message.get("content");

            // 解析AI评分结果
            Map<String, Object> scoreResult = parseAIScoreResponse(content);

            // 创建响应对象
            AiScoreQuestionResponseVM responseVM = new AiScoreQuestionResponseVM();

            // 设置分数（确保在题目分数范围内）
            Integer aiScore = (Integer) scoreResult.get("score");
            responseVM.setScore(Math.min(aiScore, model.getQuestionScore()));

            // 设置评分理由
            responseVM.setReason((String) scoreResult.get("reason"));

            return RestResponse.ok(responseVM);
        } catch (Exception e) {
            log.error("AI评分异常", e);
            return RestResponse.fail(3, "AI评分服务异常: " + e.getMessage());
        }
    }

    /**
     * 构建评分提示词
     * 
     * @param model 评分请求参数
     * @return 评分提示词
     */
    private String buildScoringPrompt(AiScoreQuestionRequestVM model) {
        StringBuilder prompt = new StringBuilder();
        String questionTypeName = getQuestionTypeName(model.getQuestionType());

        prompt.append("请根据以下信息对学生的答案进行评分：\n\n");
        prompt.append("题目类型：").append(questionTypeName).append("\n");
        prompt.append("题目内容：").append(model.getQuestionTitle()).append("\n");
        prompt.append("标准答案：").append(model.getCorrectAnswer()).append("\n");
        prompt.append("学生答案：").append(model.getUserAnswer()).append("\n");
        prompt.append("满分分值：").append(model.getQuestionScore()).append("\n\n");

        prompt.append("请根据学生答案与标准答案的匹配程度，给出一个0到").append(model.getQuestionScore()).append("之间的分数，并简要说明评分理由。\n");
        prompt.append("回复格式为：\n");
        prompt.append("分数：[数字]\n");
        prompt.append("理由：[评分理由]");

        return prompt.toString();
    }

    /**
     * 解析AI评分响应
     * 
     * @param content AI响应内容
     * @return 解析结果
     */
    private Map<String, Object> parseAIScoreResponse(String content) {
        Map<String, Object> result = new HashMap<>();

        // 默认值
        result.put("score", 0);
        result.put("reason", "无法解析AI评分结果");

        // 尝试解析分数
        if (content.contains("分数：")) {
            String[] lines = content.split("\n");
            for (String line : lines) {
                if (line.startsWith("分数：")) {
                    try {
                        String scoreStr = line.substring("分数：".length()).trim();
                        // 处理可能的小数点
                        if (scoreStr.contains(".")) {
                            scoreStr = scoreStr.substring(0, scoreStr.indexOf("."));
                        }
                        Integer score = Integer.parseInt(scoreStr);
                        result.put("score", score);
                    } catch (NumberFormatException e) {
                        log.error("解析AI分数失败", e);
                    }
                } else if (line.startsWith("理由：")) {
                    String reason = line.substring("理由：".length()).trim();
                    result.put("reason", reason);
                }
            }
        }

        return result;
    }
}
